﻿using System;
using System.Collections.Generic;
using System.Text;

namespace IMMeDotNet {

	/// <summary>
	/// Stores event arguments that refer to a <see cref="Connection"/>.
	/// </summary>
	public class ConnectionEventArgs : EventArgs {

		/// <summary>
		/// Gets the <see cref="Connection"/> that the event relates to.
		/// </summary>
		public Connection Connection { get; private set; }

		/// <summary>
		/// Creates an instance of the <see cref="ClientEventArgs"/> class.
		/// </summary>
		/// <param name="contact">The <see cref="Connection"/> that the event releates to.</param>
		public ConnectionEventArgs(Connection contact) {
			this.Connection = contact;
		}
	}


	/// <summary>
	/// A delegate used for events that relate to contacts.
	/// </summary>
	/// <param name="sender">The object that triggered the client event.</param>
	/// <param name="e">Arguments relating to the client.</param>
	public delegate void ConnectionEventHandler(object sender, ConnectionEventArgs e);

	/// <summary>
	/// Stores event arguments that refer to a <see cref="Contact"/>.
	/// </summary>
	public class ContactEventArgs : EventArgs {
	
		/// <summary>
		/// Gets the <see cref="Contact"/> that the event relates to.
		/// </summary>
		public Contact Contact { get; private set; }

		/// <summary>
		/// Creates an instance of the <see cref="ClientEventArgs"/> class.
		/// </summary>
		/// <param name="contact">The <see cref="Contact"/> that the event releates to.</param>
		public ContactEventArgs(Contact contact) {
			this.Contact = contact;
		}
	}

	/// <summary>
	/// A delegate used for events that relate to contacts.
	/// </summary>
	/// <param name="sender">The object that triggered the client event.</param>
	/// <param name="e">Arguments relating to the client.</param>
	public delegate void ContactEventHandler(object sender, ContactEventArgs e);

	/// <summary>
	/// Stores event arguments that refer to a friend of a <see cref="Contact"/>.
	/// </summary>
	public class FriendEventArgs : ConnectionEventArgs {

		/// <summary>
		/// Gets or sets the friend of the <see cref="Contact"/>.
		/// </summary>
		public Contact Friend { get; set; }

		/// <summary>
		/// Creates an instance of <see cref="FriendEventArgs"/>.
		/// </summary>
		public FriendEventArgs(Connection connection, Contact friend)
			: base(connection) {
			this.Friend = friend;
		}
	}

	/// <summary>
	/// A delegate used for events for contact friends.
	/// </summary>
	/// <param name="sender">The object that triggered the friend event.</param>
	/// <param name="e">Arguments relating to the attempted friend event.</param>
	public delegate void FriendEventHandler(object sender, FriendEventArgs e);

	/// <summary>
	/// Stores event arguments that refer to an attempt to log in.
	/// </summary>
	public class AuthenticatedContactEventArgs : ContactEventArgs {

		/// <summary>
		/// Gets the password used to log in with.
		/// </summary>
		public IMMeString Password { get; private set; }

		/// <summary>
		/// Gets or sets whether the authentication attempt was successful or not.
		/// </summary>
		public bool Success { get; set; }

		/// <summary>
		/// Creates an instance of the <see cref="AuthenticatedContactEventArgs"/> class.
		/// </summary>
		/// <param name="contact">The <see cref="AuthenticatedContact"/> that the event relates to.</param>
		/// <param name="password">The password used to log in with.</param>
		/// <param name="success">Whether the authentication attempt is successful or not.</param>
		public AuthenticatedContactEventArgs(Contact contact, IMMeString password, bool success)
			: base(contact) {
			this.Password = password;
			this.Success = success;
		}
	}

	/// <summary>
	/// A delegate used for events for authentication attempts.
	/// </summary>
	/// <param name="sender">The object that triggered the attempted log in event.</param>
	/// <param name="e">Arguments relating to the attempted log in.</param>
	public delegate void AuthenticatedContactEventHandler(object sender, AuthenticatedContactEventArgs e);

	/// <summary>
	/// Stores event arguments that refer to a message being sent.
	/// </summary>
	public class MessageEventArgs : ConnectionEventArgs {

		/// <summary>
		/// Gets the <see cref="Message"/>.
		/// </summary>
		public Message Message { get; private set; }

		/// <summary>
		/// Creates an instance of the <see cref="MessageEventArgs"/> class.
		/// </summary>
		/// <param name="message">The message that was sent.</param>
		public MessageEventArgs(Connection connection, Message message)
			: base(connection) {
			this.Message = message;
		}

	}

	/// <summary>
	/// A delegate used for events for messages.
	/// </summary>
	/// <param name="sender">The object that triggered the message event.</param>
	/// <param name="e">Arguments relating to the message.</param>
	public delegate void MessageEventHandler(object sender, MessageEventArgs e);

	partial class Host {

		/// <summary>
		/// An event that is fired when somebody attempts to log in.
		/// </summary>
		public event AuthenticatedContactEventHandler AttemptedLogIn;

		/// <summary>
		/// An event that is fired when somebody attempts to log in.
		/// </summary>
		/// <param name="e"></param>
		protected virtual void OnAttemptedLogIn(AuthenticatedContactEventArgs e) {
			if (this.AttemptedLogIn != null) {
				this.AttemptedLogIn(this, e);
			}
		}

		/// <summary>
		/// An event that is fired when somebody logs in.
		/// </summary>
		public event ConnectionEventHandler LogIn;

		/// <summary>
		/// An event that is fired when someody logs in.
		/// </summary>
		/// <param name="e">The client that has logged in.</param>
		protected virtual void OnLogIn(ConnectionEventArgs e) {
			if (this.LogIn != null) {
				this.LogIn(this, e);
			}
		}

		/// <summary>
		/// An event that is fired when somebody logs out.
		/// </summary>
		public event ConnectionEventHandler LogOff;

		/// <summary>
		/// An event that is fired when someody logs off.
		/// </summary>
		/// <param name="e">The client that has logged off.</param>
		protected virtual void OnLogOff(ConnectionEventArgs e) {
			if (this.LogOff != null) {
				this.LogOff(this, e);
			}
		}

		/// <summary>
		/// An event that is fired when the contact list is initially requested.
		/// </summary>
		public event ConnectionEventHandler RequestFriendList;

		/// <summary>
		/// An event that is fired when the contact list is initially requested.
		/// </summary>
		/// <param name="e">The list of friends that has been requested.</param>
		protected virtual void OnRequestContactList(ConnectionEventArgs e) {
			if (this.RequestFriendList != null) {
				this.RequestFriendList(this, e);
			}
		}

		/// <summary>
		/// An event that is fired when the online friend list is requested.
		/// </summary>
		public event ConnectionEventHandler RequestOnlineFriendList;

		/// <summary>
		/// An event that is fired when the online friend list is requested
		/// </summary>
		/// <param name="e">The list of online friends that has been requested.</param>
		protected virtual void OnRequestOnlineFriendList(ConnectionEventArgs e) {
			if (this.RequestOnlineFriendList != null) {
				this.RequestOnlineFriendList(this, e);
			}
		}

		/// <summary>
		/// An event that is fired when an incoming message is received.
		/// </summary>
		public event MessageEventHandler MessageReceived;

		/// <summary>
		/// An event that is fired when an incoming message is received.
		/// </summary>
		/// <param name="e">The message that has been received.</param>
		protected virtual void OnMessageReceived(MessageEventArgs e) {
			if (this.MessageReceived != null) {
				this.MessageReceived(this, e);
			}
		}

		/// <summary>
		/// An event that is fired when a message has been sent and acknowledged.
		/// </summary>
		public event MessageEventHandler MessageSent;

		/// <summary>
		/// An event that is fired when a message has been sent and acknowledged.
		/// </summary>
		/// <param name="e">The message that has been sent.</param>
		protected virtual void OnMessageSent(MessageEventArgs e) {
			if (this.MessageSent != null) {
				this.MessageSent(this, e);
			}
		}

		/// <summary>
		/// An event that is fired when a friend has been removed from a contact's friend list.
		/// </summary>
		public event FriendEventHandler FriendRemoved;

		/// <summary>
		/// An event that is fired when a friend has been removed from a contact's friend list.
		/// </summary>
		/// <param name="e">The contact and the friend that has been removed from their friend list.</param>
		protected virtual void OnFriendRemoved(FriendEventArgs e) {
			if (this.FriendRemoved != null) {
				this.FriendRemoved(this, e);
			}
		}

		/// <summary>
		/// An event that is fired when a friend has been added to a contact's friend list.
		/// </summary>
		public event FriendEventHandler FriendAdded;

		/// <summary>
		/// An event that is fired when a friend has been added to a contact's friend list.
		/// </summary>
		/// <param name="e">The contact and the friend that has been removed from their friend list.</param>
		protected virtual void OnFriendAdded(FriendEventArgs e) {
			if (this.FriendAdded != null) {
				this.FriendAdded(this, e);
			}
		}

		/// <summary>
		/// An event that is fired when a discussion has ended.
		/// </summary>
		public event FriendEventHandler DiscussionEnded;

		/// <summary>
		/// An event that is fired when a discussion has ended.
		/// </summary>
		/// <param name="e">The contact and the friend that has been removed from their friend list.</param>
		protected virtual void OnDiscussionEnded(FriendEventArgs e) {
			if (this.DiscussionEnded != null) {
				this.DiscussionEnded(this, e);
			}
		}

	}
}
